#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: logistic_regression.py
# 逻辑回归示例

import numpy as np
from sklearn import datasets
# 因为逻辑回归的本质是线性回归的一个缩放，所以本质就是线性回归，所以逻辑回归的包就在线性回归包中
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
from time import time

# iris：鸢尾花，加载鸢尾花数据集
iris = datasets.load_iris()
print(list(iris.keys()))
print(iris['DESCR'])
print(iris['feature_names'])

# X = iris['data'][:, 3:]
X = iris['data']
# print(X)

# print(iris['target'])
y = iris['target']


# y = (iris['target'] == 2).astype(np.int)
# print(y)


# Utility function to report best scores
def report(results, n_top=3):
    for i in range(1, n_top + 1):
        candidates = np.flatnonzero(results['rank_test_score'] == i)
        for candidate in candidates:
            print("Model with rank: {0}".format(i))
            print("Mean validation score: {0:.3f} (std: {1:.3f})".format(
                results['mean_test_score'][candidate],
                results['std_test_score'][candidate]))
            print("Parameters: {0}".format(results['params'][candidate]))
            print("")


# 开始做模型评估
start = time()
# tol：Tolerance；C：反向正则化参数；用来调整泛化能力的，值越小繁华能力越强；
param_grid = {"tol": [1e-4, 1e-3, 1e-2],
              "C": [0.4, 0.6, 0.8]}
# ovr是默认值，表示二分类；sag表示梯度下降法
# multi_class如果选择ovr，这个时候也是一个多酚类问题，就会把这个多分类问题转化成多个二分类问题，选择multinomial，则会交给softmax解决
# ConvergenceWarning：收敛警告，如果结果没有收敛就会报这个警告，这个时候可以调大max_iter(最大迭代次数)来解决这个问题
lr_model = LogisticRegression(multi_class='ovr', solver='sag', max_iter=10000)
# 给创建的模型绑定超参集和交叉验证折数，把绑定之后的数据生成一个对象：方格搜索交叉验证对象
# lr_model：验证的模型；param_grid：超参集，，是一个字典；cv：Cross Validation的折数，即使用几折交叉验证，数据是随机分组的
grid_search = GridSearchCV(lr_model, param_grid=param_grid, cv=3)
# 选择使用逻辑回归模型训练模型，容易出现过拟合，因为没有超参集
# lr_model.fit(X, y)
# 利用方格搜索交叉验证对象，开始训练，如果这里使用grid_search来训练，那么后面豆芽使用grid_search来回去结果，而不是lr_model
grid_search.fit(X, y)
# 计算训练的时长
# print("GridSearchCV took %.2f seconds for %d candidate parameter settings."
#       % (time() - start, len(grid_search.cv_results_['params'])))
# 输出训练结果
# report(grid_search.cv_results_)

# 开始绘图，创建新的数据集：linspace：从0到3这个区间范围(花瓣宽度)按照顺序取1000个数值，不是随机
# X_new = np.linspace(0, 3, 1000).reshape(-1, 1)
# print(X_new)
#
# # 分到某个分类号的概率
# y_proba = lr_model.predict_proba(X_new)
# # predict预测分类号
# y_hat = lr_model.predict(X_new)
# print(y_proba)
# print(y_hat)
# 输出匹配度最好的超参
# print("W:\n", grid_search.best_estimator_)
print("W:\n", lr_model.coef_)
print("w_0:\n", lr_model.intercept_)

# 绘制不同类别的花的分类效果
# plt.plot(X_new, y_proba[:, 2], 'g-', label='Iris-Virginica')
# plt.plot(X_new, y_proba[:, 1], 'r-', label='Iris-Versicolour')
# plt.plot(X_new, y_proba[:, 0], 'b--', label='Iris-Setosa')
# plt.show()

# print("lr_model.predict([[1.7], [1.5]])=\n", lr_model.predict([[1.7], [1.5]]))
